package ru.mirent.console.colors;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;

import java.util.stream.Stream;

/**
 * Демонстрация вывода форматированного текста в консоль IDE.
 * В некоторых случаях при совпаении цвета букв текста с фоном не выдно выведенного текста, для того, чтобы увидеть
 * его, необходимо его выделить курсором мыши.
 * Так же реализован класс для вывода форматированного текста в консоль {@link FormatterTextColor}.
 */
public class ConsoleColorsTest {
    private static final String BLACK = "Черный";
    private static final String BLACK_BRIGHT = "Черный осветленный";
    private static final String RED = "Красный";
    private static final String RED_BRIGHT = "Красный светлый";
    private static final String GREEN = "Зеленый";
    private static final String GREEN_BRIGHT = "Зеленый светлый";
    private static final String YELLOW = "Желтый";
    private static final String YELLOW_BRIGHT = "Желтый светлый";
    private static final String BLUE = "Синий";
    private static final String BLUE_BRIGHT = "Синий светлый";
    private static final String MAGENTA = "Фиолетовый";
    private static final String MAGENTA_BRIGHT = "Фиолетовый светлый";
    private static final String CYAN = "Голубой";
    private static final String CYAN_BRIGHT = "Голубой светлый";
    private static final String WHITE = "Серый";
    private static final String WHITE_BRIGHT = "Серый светлый";
    private static final String DEFAULT = "По умолчанию";
    private static final String DEFAULT_BRIGHT = "По умолчанию светлый";

    @ParameterizedTest
    @ArgumentsSource(BackgroundColorsTestData.class)
    void backgroundColorTest(BgColor bgColor, String color) {
        System.out.printf("%n");
        String template = "\033[%smПример с цветом фона: %s\033[0m";
        String text = String.format(template, bgColor.getValue(), color);
        System.out.println(text);
    }

    @ParameterizedTest
    @ArgumentsSource(TextColorsTestData.class)
    void textColorTest(TextColor textColor, String color) {
        System.out.printf("%n");
        String template = "\033[%smПример с цветом фона: %s\033[0m";
        String text = String.format(template, textColor.getValue(), color);
        System.out.println(text);
    }

    /**
     * Пример вывода 8-bit цветовой палитры, где все цвета пронумерованы от 0 до 255. Всего 256 цветов.
     * Цвета фона текста и цвет букв инвертированы относительно друг друга.
     * <p>Цвет формируется по шаблону: \033[48;5;3;38;5;12mТекст\033[0m, где;
     * <p>- \033[ - управляющий символ цветовой последовательности;
     * <p>- 48;5;3 - 48: код установки фона текста, 5: код для указания палитры 8-bit; 3: код цвета, устанавливаемый
     * для фона;
     * <p>- 38;5;12 -38: код установки цвета букв текста; 5: код для указания палитры 8-bit; 12: код цвета,
     * устанавливаемый для цвета букв;
     * <p>- 0 - код, указывающий на сброс всех стилей на значения по умолчанию;
     * <p>- m - признак завершения указаная стиля;
     * <p>- Текст - текст, который будет выведен с данным стилем.
     */
    @Test
    void table8bitColorTest() {
        System.out.printf("%n");
        String templateBc = "\033[%s;%sm %2d %2d \033[0m";
        for (int i = 0; i <= 15; i++) {
            String backgroundColor = BgColor.create(i).getValue();
            String textColor = TextColor.create(15 - i).getValue();
            String text = String.format(templateBc, backgroundColor, textColor, i, 15 - i);
            System.out.printf(text);

            if (((i - 15) % 4) == 0) {
                System.out.print(System.lineSeparator());
            }
        }

        System.out.print(System.lineSeparator());

        String templateTc = "\033[%s;%sm %3d %3d \033[0m";
        for (int i = 16; i <= 255; i++) {
            String backgroundColor = BgColor.create(i).getValue();
            String textColor = TextColor.create(255 + 16 - i).getValue();
            System.out.printf(templateTc, backgroundColor, textColor, i, 255 + 16 - i);

            if (((i - 15) % 12) == 0) {
                System.out.print(System.lineSeparator());
            }
        }
    }

    /**
     * В данном примере показано формирование цвета с укзанием RGB значений, что позволяет сформировать любой цвет.
     * Для ограничения выведены градиенты основных цветов, но их можно комбинировать. Формирование цвета происходит
     * так же как в примере {@link #table8bitColorTest()} с отличием в том, что значение кода установки фона текста
     * вместо 48 имеет равен 38.
     */
    @Test
    void tableRGBColorTest() {
        System.out.printf("%n");

        String template = "\033[%s;%sm %3d %3d \033[0m";
        for (int i = 0; i <= 255; i++) {
            String backgroundColor = BgColor.create(i, 0, 0).getValue();
            String textColor = TextColor.create(TC.DEFAULT).getValue();
            System.out.printf(template, backgroundColor, textColor, i, 255 + 16 - i);

            if (((i + 1) % 8) == 0) {
                System.out.print(System.lineSeparator());
            }
        }
        for (int i = 0; i <= 255; i++) {
            String backgroundColor = BgColor.create(0, i, 0).getValue();
            String textColor = TextColor.create(TC.DEFAULT).getValue();
            System.out.printf(template, backgroundColor, textColor, i, 255 + 16 - i);

            if (((i + 1) % 8) == 0) {
                System.out.print(System.lineSeparator());
            }
        }
        for (int i = 0; i <= 255; i++) {
            String backgroundColor = BgColor.create(0, 0, i).getValue();
            String textColor = TextColor.create(TC.DEFAULT).getValue();
            System.out.printf(template, backgroundColor, textColor, i, 255 + 16 - i);

            if (((i + 1) % 8) == 0) {
                System.out.print(System.lineSeparator());
            }
        }
    }

    private static class BackgroundColorsTestData implements ArgumentsProvider {
        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
            return Stream.of(
                    Arguments.of(BgColor.create(BC.BLACK), BLACK),
                    Arguments.of(BgColor.create(BC.BLACK_BRIGHT), BLACK_BRIGHT),
                    Arguments.of(BgColor.create(BC.RED), RED),
                    Arguments.of(BgColor.create(BC.RED_BRIGHT), RED_BRIGHT),
                    Arguments.of(BgColor.create(BC.GREEN), GREEN),
                    Arguments.of(BgColor.create(BC.GREEN_BRIGHT), GREEN_BRIGHT),
                    Arguments.of(BgColor.create(BC.YELLOW), YELLOW),
                    Arguments.of(BgColor.create(BC.YELLOW_BRIGHT), YELLOW_BRIGHT),
                    Arguments.of(BgColor.create(BC.BLUE), BLUE),
                    Arguments.of(BgColor.create(BC.BLUE_BRIGHT), BLUE_BRIGHT),
                    Arguments.of(BgColor.create(BC.MAGENTA), MAGENTA),
                    Arguments.of(BgColor.create(BC.MAGENTA_BRIGHT), MAGENTA_BRIGHT),
                    Arguments.of(BgColor.create(BC.CYAN), CYAN),
                    Arguments.of(BgColor.create(BC.CYAN_BRIGHT), CYAN_BRIGHT),
                    Arguments.of(BgColor.create(BC.WHITE), WHITE),
                    Arguments.of(BgColor.create(BC.WHITE_BRIGHT), WHITE_BRIGHT),
                    Arguments.of(BgColor.create(BC.DEFAULT), DEFAULT),
                    Arguments.of(BgColor.create(BC.DEFAULT_BRIGHT), DEFAULT_BRIGHT),
                    Arguments.of(BgColor.create(111), "Цвет из палитры: голубой"),
                    Arguments.of(BgColor.create(0, 255, 0), "RGB-цвет: Ярко-зеленый")
            );
        }
    }

    private static class TextColorsTestData implements ArgumentsProvider {
        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
            return Stream.of(
                    Arguments.of(TextColor.create(TC.BLACK), BLACK),
                    Arguments.of(TextColor.create(TC.BLACK_BRIGHT), BLACK_BRIGHT),
                    Arguments.of(TextColor.create(TC.RED), RED),
                    Arguments.of(TextColor.create(TC.RED_BRIGHT), RED_BRIGHT),
                    Arguments.of(TextColor.create(TC.GREEN), GREEN),
                    Arguments.of(TextColor.create(TC.GREEN_BRIGHT), GREEN_BRIGHT),
                    Arguments.of(TextColor.create(TC.YELLOW), YELLOW),
                    Arguments.of(TextColor.create(TC.YELLOW_BRIGHT), YELLOW_BRIGHT),
                    Arguments.of(TextColor.create(TC.BLUE), BLUE),
                    Arguments.of(TextColor.create(TC.BLUE_BRIGHT), BLUE_BRIGHT),
                    Arguments.of(TextColor.create(TC.MAGENTA), MAGENTA),
                    Arguments.of(TextColor.create(TC.MAGENTA_BRIGHT), MAGENTA_BRIGHT),
                    Arguments.of(TextColor.create(TC.CYAN), CYAN),
                    Arguments.of(TextColor.create(TC.CYAN_BRIGHT), CYAN_BRIGHT),
                    Arguments.of(TextColor.create(TC.WHITE), WHITE),
                    Arguments.of(TextColor.create(TC.WHITE_BRIGHT), WHITE_BRIGHT),
                    Arguments.of(TextColor.create(TC.DEFAULT), DEFAULT),
                    Arguments.of(TextColor.create(TC.DEFAULT_BRIGHT), DEFAULT_BRIGHT),
                    Arguments.of(TextColor.create(111), "Цвет из палитры: голубой"),
                    Arguments.of(TextColor.create(0, 255, 0), "RGB-цвет: Ярко-зеленый")
            );
        }
    }

    @Test
    void qwdTest() {
        System.out.printf("%n");
        String template = "\033[%sm %s \033[%sm";
        String text = String.format(template,
                ControlCharacters.BOLD.getValue(),
                "Пример",
                ControlCharacters.BOLD_OFF_OR_DOUBLE_UNDERLINE.getValue());

//        System.out.println("Текст до" + text + "Текст после");
        System.out.println("\033[1m 123 \033[0m 234");
        System.out.println("\033[1m 123 \033[21m 234");
        System.out.println("\033[21m 123 \033[0m 234");
        System.out.println("\033[4m 123 \033[0m 234");
        System.out.println("\033[4m 123 \033[24m 234");
    }
}
